package org.linlinjava.litemall.wx.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.express.ExpressService;
import org.linlinjava.litemall.core.express.dao.ExpressInfo;
import org.linlinjava.litemall.core.notify.*;
import org.linlinjava.litemall.core.payment.DefaultCurType;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.DateTimeUtil;
import org.linlinjava.litemall.core.util.IpUtil;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.ResponseUtil.Response;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.dto.LitemallAccountBookFormDto;
import org.linlinjava.litemall.db.dto.WebOrderGoodsRemarkDTO;
import org.linlinjava.litemall.db.dto.WxMemberSourceDTO;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.*;
import org.linlinjava.litemall.wx.bo.OrderGoodsBo;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.dto.WxOrderStatusDTO;
import org.linlinjava.litemall.wx.errorcode.ErrorCodeConstants;
import org.linlinjava.litemall.wx.util.LocationUtils;
import org.linlinjava.litemall.wx.util.WxResponseEnum;
import org.linlinjava.litemall.wx.vo.*;
import org.linlinjava.litemall.wx.vo.cart.CartListRespVO;
import org.linlinjava.litemall.wx.vo.order.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.DelayQueue;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.core.exception.util.ServiceExceptionUtil.exception;
import static org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_ONGOING;
import static org.linlinjava.litemall.db.beans.Constants.ORDER_STATUS_UNPAID;
import static org.linlinjava.litemall.wx.util.WxResponseCode.*;

/**
 * 订单服务
 *
 * <p>
 * 订单状态：
 * 101 订单生成，未支付；102，下单后未支付用户取消；103，下单后未支付超时系统自动取消
 * 201 支付完成，商家未发货；202，订单生产，已付款未发货，但是退款取消；
 * 301 商家发货，用户未确认；
 * 401 用户确认收货； 402 用户没有确认收货超过一定时间，系统自动确认收货；
 *
 * <p>
 * 用户操作：
 * 当101用户未付款时，此时用户可以进行的操作是取消订单，或者付款操作
 * 当201支付完成而商家未发货时，此时用户可以取消订单并申请退款
 * 当301商家已发货时，此时用户可以有确认收货的操作
 * 当401用户确认收货以后，此时用户可以进行的操作是删除订单，评价商品，或者再次购买
 * 当402系统自动确认收货以后，此时用户可以删除订单，评价商品，或者再次购买
 *
 * <p>
 * 注意：目前不支持订单退货和售后服务
 */
@Service
@Transactional
public class WxOrderService {
    private final Log logger = LogFactory.getLog(WxOrderService.class);

    private DelayQueue<LitemallOrder> delayQueue = new DelayQueue<>();
    @Resource
    private ThreadPoolTaskExecutor executorService;

    @Autowired
    private LitemallUserService userService;
    @Autowired
    private LitemallOrderService orderService;

    @Autowired
    private LumiereOrderService lumiereOrderService;

    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    @Autowired
    private LitemallAddressService addressService;
    @Autowired
    private LitemallCartService cartService;
    @Autowired
    private LitemallRegionService regionService;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private NotifyService notifyService;
    @Autowired
    private LitemallUserFormIdService formIdService;
    @Autowired
    private ExpressService expressService;
    @Autowired
    private LitemallCommentService commentService;
    @Autowired
    private LitemallCouponUserService couponUserService;
    @Autowired
    private CouponVerifyService couponVerifyService;
    @Autowired
    private LitemallGoodsService goodsService;
    @Autowired
    private LumiereFormulaSpecificationsService lumiereFormulaSpecificationsService;
    @Autowired
    private LumiereFormulaSpecificationsDataProportioningService lumiereFormulaSpecificationsDataProportioningService;
    @Autowired
    private LumiereFormulaMaterialService lumiereFormulaMaterialService;
    @Autowired
    private LumierePackageService lumierePackageService;
    @Autowired
    private LitemallOrderPackageService litemallOrderPackageService;
    @Autowired
    private LitemallOrderFormulaMaterialService litemallOrderFormulaMaterialService;
    @Autowired
    private LitemallGoodsSpecificationService goodsSpecificationService;
    @Autowired
    private LitemallShopService shopService;
    @Autowired
    private NoticeHelper noticeHelper;
    @Autowired
    private LitemallTaxService litemallTaxService;
    @Autowired
    private LitemallShopRegionService litemallShopRegionService;
    @Autowired
    private LitemallOrderTaxService litemallOrderTaxService;
    @Autowired
    private AwsNotifyService awsNotifyService;
    @Autowired
    private LitemallAdminService litemallAdminService;
    @Autowired
    private LitemallGoodsAccessoryService litemallGoodsAccessoryService;
    @Autowired
    private LitemallCartGoodsAccessoryService litemallCartGoodsAccessoryService;
    @Autowired
    private LitemallOrderGoodsAccessoryService litemallOrderGoodsAccessoryService;
    @Autowired
    private LitemallMerchandiseService litemallMerchandiseService;
    @Autowired
    private LitemallShopMerchandiseService litemallShopMerchandiseService;
    @Autowired
    private LitemallGoodsRegionService goodsRegionService;
    @Autowired
    private LitemallOrderGoodsPropertyService litemallOrderGoodsPropertyService;
    @Autowired
    private LitemallCartGoodsPropertyService litemallCartGoodsPropertyService;
    @Autowired
    private LitemallGoodsPropertyService litemallGoodsPropertyService;
    @Autowired
    private PosPushSender posPushSender;
    @Autowired
    private LumierePayMemberUserService payMemberUserService;
    @Autowired
    private LumierePayMemberService lumierePayMemberService;

    @Autowired
    private LitemallRefundService litemallRefundService;

    @Autowired
    private LumiereCouponUserService lumiereCouponUserService;

    @Autowired
    private LumiereCouponStrategyService lumiereCouponStrategyService;

    @Autowired
    private LitemallAccountBookService litemallAccountBookService;

    @Autowired
    private LitemallOrderMerchandiseService orderMerchandiseService;

    @Autowired
    private LumiereCartService lumiereCartService;

    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;




    public Response orderStatusS(Integer userId, WxOrderStatusDTO wxOrderStatusDTO) {
        //根据类型拿到用户所有订单
        List<LitemallOrder> orderList = orderService.list(Wrappers.lambdaQuery(LitemallOrder.class)
                .eq(LitemallOrder::getUserId, userId)
                .in(wxOrderStatusDTO.getOrderStatus().length>0,LitemallOrder::getOrderStatus, wxOrderStatusDTO.getOrderStatus())
                .in(wxOrderStatusDTO.getRefundStatus().length>0,LitemallOrder::getRefundStatus, wxOrderStatusDTO.getRefundStatus())
                .in(wxOrderStatusDTO.getEvaluationStatus().length>0,LitemallOrder::getEvaluationStatus, wxOrderStatusDTO.getEvaluationStatus())
                .in(wxOrderStatusDTO.getMadeStatus().length>0,LitemallOrder::getMadeStatus, wxOrderStatusDTO.getMadeStatus())
                .in(wxOrderStatusDTO.getOrderType().length>0,LitemallOrder::getOrderType, wxOrderStatusDTO.getOrderType())
                .eq(LitemallOrder::getDeleted,0)
                .orderByDesc(LitemallOrder::getAddTime)
        );


        //过滤一些不是下单的订单，比如礼物卡充值
//        wxLitemallOrderVoList=wxLitemallOrderVoList.stream().filter(filterOrder->{
//            return (filterOrder.getGstPrice()!=null&&filterOrder.getPstPrice()!=null&&filterOrder.getHstPrice()!=null)||filterOrder.getExId()!=null;
//        }).collect(Collectors.toList());
        List<WxOrderListVo> wxOrderListVoList = CollUtil.newArrayList();
        orderList.stream().forEach(litemallOrder->{
            WxLitemallOrderVo wxLitemallOrderVo = WxLitemallOrderVo.builder().build();
            BeanUtils.copyProperties(litemallOrder,wxLitemallOrderVo);
            wxLitemallOrderVo.setLitemallShop( litemallOrder.getShopId()!=null?shopService.getInfoById(litemallOrder.getShopId()):null);
            //封装 订单->[子订单]
            WxOrderListVo wxOrderListVo = WxOrderListVo.builder()
                    .wxLitemallOrderVo(wxLitemallOrderVo)
                    .litemallOrderGoodsList(orderGoodsService.queryByOid(litemallOrder.getId()))
                    .build();
            wxOrderListVoList.add(wxOrderListVo);
        });
        PageTools pageTools = PageTools.builder().build();
        pageTools.pageTools(wxOrderStatusDTO.getPage(),wxOrderStatusDTO.getLimit(),wxOrderListVoList);
        return ResponseUtil.ok(pageTools);
    }

    /**
     * 订单列表
     *
     * @param userId   用户ID
     * @param showType 订单信息：
     *                 0，全部订单；
     *                 1，待付款；
     *                 2，待发货；
     *                 3，待收货；
     *                 4，待评价。
     * @param page     分页页数
     * @param limit    分页大小
     * @return 订单列表
     */
    public Response list(Integer userId, Integer showType, Integer page, Integer limit, String sort, String order) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        /**
         List<Short> orderStatus = OrderUtil.orderStatus(showType);
         List<LitemallOrder> orderList = orderService.queryByOrderStatus(userId, orderStatus, page, limit, sort, order);
         */
        List<Short> orderStatus = OrderStatusUtil.orderStatus(showType);
        Byte evaluationStatus = null;//评价状态
        if (showType == 4) {
            //订单状态为待评价
            evaluationStatus = Constants.ORDER_EVALUATION_STATUS_NONE;
        }


        //PageHelper.startPage(page, limit);
        LambdaQueryWrapper<LitemallOrder> orderLambdaQueryWrapper = new LambdaQueryWrapper();
        orderLambdaQueryWrapper.in(orderStatus.size()>0,LitemallOrder::getOrderStatus,orderStatus);
        orderLambdaQueryWrapper.eq(LitemallOrder::getUserId,userId);
        orderLambdaQueryWrapper.eq(evaluationStatus!=null,LitemallOrder::getEvaluationStatus,evaluationStatus);
        orderLambdaQueryWrapper.orderByDesc(LitemallOrder::getPayTime);
        List<LitemallOrder> orderList = orderService.list(orderLambdaQueryWrapper);
        //List<LitemallOrder> orderList = orderService.queryByOrderStatusAndEvaluationStatus(userId, evaluationStatus, orderStatus, page, limit, sort, order);
        //过滤一些不是下单的订单，比如礼物卡充值
        /*orderList=orderList.stream().filter(filterOrder->{
            return filterOrder.getMadeStatus()!=null&&filterOrder.getOrderType()!=null&&filterOrder.getGstPrice()!=null&&filterOrder.getPstPrice()!=null&&filterOrder.getHstPrice()!=null;
        }).collect(Collectors.toList());*/
        List<OrderListRespVO> orderListResp = new ArrayList<>();
        for (LitemallOrder litemallOrder : orderList) {
            OrderListRespVO orderRespVO = new OrderListRespVO();
            orderRespVO.setId(litemallOrder.getId());
            orderRespVO.setOrderSn(litemallOrder.getOrderSn());
            orderRespVO.setActualPrice(litemallOrder.getActualPrice());
            orderRespVO.setOrderStatusText(OrderStatusUtil.orderStatusText(litemallOrder));
            orderRespVO.setTaxPrice(litemallOrder.getTaxPrice());
            orderRespVO.setOrderStatus(litemallOrder.getOrderStatus());
            orderRespVO.setMadeStatus(litemallOrder.getMadeStatus());
            orderRespVO.setHandleOption(OrderStatusUtil.build(litemallOrder));
            orderRespVO.setShop(litemallOrder.getShopId()==null?null:shopService.findById(litemallOrder.getShopId()));
            orderRespVO.setMessage(litemallOrder.getMessage());
            orderRespVO.setOrderType(litemallOrder.getOrderType());
            orderRespVO.setFreightPrice(litemallOrder.getFreightPrice());
            orderRespVO.setAddress(litemallOrder.getAddress());
            orderRespVO.setPoint(litemallOrder.getPoints());
            orderRespVO.setPayType(litemallOrder.getPayType());

            orderRespVO.setGoodsPrice(litemallOrder.getGoodsPrice());

            //商品
            if(litemallOrder.getGoodsIds().size()>0){
                List<LitemallOrderGoods> orderGoodsList = litemallOrderGoodsService.getOrderGoodsByIds(litemallOrder.getGoodsIds());
                List<OrderGoodsRespVO> orderGoodsRespList = CollStreamUtil.toList(orderGoodsList, orderGoods -> new OrderGoodsRespVO()
                        .setId(orderGoods.getId()).setGoodsName(orderGoods.getGoodsName()).setNumber(orderGoods.getNumber())
                        .setPicUrl(orderGoods.getPicUrl()).setSpecifications(orderGoods.getSpecifications()).setPrice(orderGoods.getPrice()).setTaxPrice(orderGoods.getTaxPrice())
                        .setFormulaMaterialList(getOrderGoodsFormulaMaterialList(orderGoods.getOrderId(),orderGoods.getId())).setPropertyList(getOrderGoodsPropertyList(orderGoods.getOrderId(),orderGoods.getId())).setTaxList(getOrderGoodsTaxList(orderGoods.getOrderId(),orderGoods.getId())));
                orderRespVO.setGoodsList(orderGoodsRespList);
            }

            //套餐
            if(litemallOrder.getPackageIds().size()>0){
                List<LitemallOrderPackage> orderPackageList = litemallOrderPackageService.listByIds(litemallOrder.getPackageIds());
                List<OrderPackageRespVO> orderPackageRespList = CollStreamUtil.toList(orderPackageList,orderPackage-> {
                    OrderPackageRespVO orderPackageResp = new OrderPackageRespVO();
                    orderPackageResp.setId(orderPackage.getId());
                    orderPackageResp.setPackageName(orderPackage.getPackageName());
                    orderPackageResp.setNumber(orderPackage.getNumber());
                    orderPackageResp.setPicUrl(orderPackage.getPackageImg());
                    orderPackageResp.setPrice(orderPackage.getAmount());
                    //套餐商品
                    List<LitemallOrderGoods> orderPackageGoodsList = litemallOrderGoodsService.getOrderGoodsByIds(orderPackage.getGoodsIds());
                    List<OrderGoodsRespVO> orderPackageGoodsRespList = CollStreamUtil.toList(orderPackageGoodsList, orderGoods -> new OrderGoodsRespVO()
                            .setId(orderGoods.getId()).setGoodsName(orderGoods.getGoodsName()).setNumber(orderGoods.getNumber())
                            .setPicUrl(orderGoods.getPicUrl()).setSpecifications(orderGoods.getSpecifications()).setPrice(orderGoods.getPrice()).setTaxPrice(orderGoods.getTaxPrice())
                            .setFormulaMaterialList(getOrderGoodsFormulaMaterialList(orderGoods.getOrderId(),orderGoods.getId())).setPropertyList(getOrderGoodsPropertyList(orderGoods.getOrderId(),orderGoods.getId())).setTaxList(getOrderGoodsTaxList(orderGoods.getOrderId(),orderGoods.getId())));
                    orderPackageResp.setGoodsList(orderPackageGoodsRespList);
                    return orderPackageResp;
                });
                orderRespVO.setPackageList(orderPackageRespList);
            }
            orderListResp.add(orderRespVO);
        }
        return ResponseUtil.okList(orderListResp,orderList);
    }

    //订单商品 配方 属性 税费
    private List<OrderGoodsFormulaMaterialRespVO>  getOrderGoodsFormulaMaterialList(Integer orderId,Integer orderGoodsId){
        List<LitemallOrderFormulaMaterial> formulaMaterialList = litemallOrderFormulaMaterialService.list(Wrappers.lambdaQuery(LitemallOrderFormulaMaterial.class)
                .eq(LitemallOrderFormulaMaterial::getOrderId, orderId)
                .eq(LitemallOrderFormulaMaterial::getOrderGoodsId, orderGoodsId));
        return Convert.convert(new TypeReference<List<OrderGoodsFormulaMaterialRespVO>>() {},formulaMaterialList);
    }

    private List<OrderGoodsPropertyRespVO>  getOrderGoodsPropertyList(Integer orderId,Integer orderGoodsId){
        List<LitemallOrderGoodsProperty> propertyList = litemallOrderGoodsPropertyService.list(Wrappers.lambdaQuery(LitemallOrderGoodsProperty.class)
                .eq(LitemallOrderGoodsProperty::getOrderId, orderId)
                .eq(LitemallOrderGoodsProperty::getOrderGoodsId, orderGoodsId));
        return Convert.convert(new TypeReference<List<OrderGoodsPropertyRespVO>>() {},propertyList);
    }

    private List<OrderGoodsTaxRespVO>  getOrderGoodsTaxList(Integer orderId,Integer orderGoodsId){
        List<LitemallOrderTax> orderTaxList = litemallOrderTaxService.queryByOrderIdAndOrderGoodsId(orderId, orderGoodsId);
        return Convert.convert(new TypeReference<List<OrderGoodsTaxRespVO>>() {},orderTaxList);
    }



    public Response detail(Integer userId, Integer orderId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        // 订单信息
        LitemallOrder litemallOrder = orderService.getById(orderId);
        if (null == litemallOrder) {
            return ResponseUtil.fail(ORDER_UNKNOWN, "订单不存在");
        }

        if (litemallOrder.getOrderSource().equals(Constants.ORDER_SOURCE_POS) && litemallOrder.getMemberId() != null && litemallOrder.getMemberId().equals(userId) != true) {
            return ResponseUtil.fail(ORDER_INVALID, "不是当前用户的订单");
        } else if (litemallOrder.getOrderSource().equals(Constants.ORDER_SOURCE_APP) && litemallOrder.getUserId().equals(userId) == false) {
            return ResponseUtil.fail(ORDER_INVALID, "不是当前用户的订单");
        }

        //订单
        OrderListRespVO orderRespVO = new OrderListRespVO();
        orderRespVO.setId(litemallOrder.getId());
        orderRespVO.setOrderSn(litemallOrder.getOrderSn());
        orderRespVO.setActualPrice(litemallOrder.getActualPrice());
        orderRespVO.setOrderStatusText(OrderStatusUtil.orderStatusText(litemallOrder));
        orderRespVO.setTaxPrice(litemallOrder.getTaxPrice());
        orderRespVO.setOrderStatus(litemallOrder.getOrderStatus());
        orderRespVO.setMadeStatus(litemallOrder.getMadeStatus());
        orderRespVO.setHandleOption(OrderStatusUtil.build(litemallOrder));
        orderRespVO.setShop(litemallOrder.getShopId()!=null?null:shopService.findById(litemallOrder.getShopId()));
        orderRespVO.setMessage(litemallOrder.getMessage());
        orderRespVO.setOrderType(litemallOrder.getOrderType());
        orderRespVO.setFreightPrice(litemallOrder.getFreightPrice());
        orderRespVO.setConsignee(litemallOrder.getConsignee());
        orderRespVO.setMobile(litemallOrder.getMobile());
        orderRespVO.setAddress(litemallOrder.getAddress());
        orderRespVO.setPoint(litemallOrder.getPoints());
        orderRespVO.setPayType(litemallOrder.getPayType());
        orderRespVO.setAddTime(litemallOrder.getAddTime());

        orderRespVO.setGSTPrice(litemallOrder.getGstPrice());
        orderRespVO.setPSTPrice(litemallOrder.getPstPrice());
        orderRespVO.setHSTPrice(litemallOrder.getHstPrice());
        orderRespVO.setMemberPer(litemallOrder.getMemberPer());
        orderRespVO.setMemberPrice(litemallOrder.getMemberPrice());
        orderRespVO.setCouponPrice(litemallOrder.getCouponPrice());
        orderRespVO.setGoodsPrice(litemallOrder.getGoodsPrice());
        orderRespVO.setWxMemberSource(JSONUtil.toList(JSONUtil.parseArray(litemallOrder.getWxMemberSource()),WxMemberSourceDTO.class));

        //商品
        if(CollUtil.isNotEmpty(litemallOrder.getGoodsIds())){
            List<LitemallOrderGoods> orderGoodsList = litemallOrderGoodsService.getOrderGoodsByIds(litemallOrder.getGoodsIds());
            List<OrderGoodsRespVO> orderGoodsRespList = CollStreamUtil.toList(orderGoodsList, orderGoods -> new OrderGoodsRespVO()
                    .setId(orderGoods.getId()).setGoodsName(orderGoods.getGoodsName()).setNumber(orderGoods.getNumber())
                    .setPicUrl(orderGoods.getPicUrl()).setSpecifications(orderGoods.getSpecifications()).setPrice(orderGoods.getPrice()).setTaxPrice(orderGoods.getTaxPrice())
                    .setFormulaMaterialList(getOrderGoodsFormulaMaterialList(orderGoods.getOrderId(),orderGoods.getId())).setPropertyList(getOrderGoodsPropertyList(orderGoods.getOrderId(),orderGoods.getId())).setTaxList(getOrderGoodsTaxList(orderGoods.getOrderId(),orderGoods.getId())));
            orderRespVO.setGoodsList(orderGoodsRespList);
        }

        //套餐
        if(CollUtil.isNotEmpty(litemallOrder.getPackageIds())){
            List<LitemallOrderPackage> orderPackageList = litemallOrderPackageService.listByIds(litemallOrder.getPackageIds());
            List<OrderPackageRespVO> orderPackageRespList = CollStreamUtil.toList(orderPackageList,orderPackage-> {
                OrderPackageRespVO orderPackageResp = new OrderPackageRespVO();
                orderPackageResp.setId(orderPackage.getId());
                orderPackageResp.setPackageName(orderPackage.getPackageName());
                orderPackageResp.setNumber(orderPackage.getNumber());
                orderPackageResp.setPicUrl(orderPackage.getPackageImg());
                orderPackageResp.setPrice(orderPackage.getAmount());
                //套餐商品
                List<LitemallOrderGoods> orderPackageGoodsList = litemallOrderGoodsService.getOrderGoodsByIds(orderPackage.getGoodsIds());
                List<OrderGoodsRespVO> orderPackageGoodsRespList = CollStreamUtil.toList(orderPackageGoodsList, orderGoods -> new OrderGoodsRespVO()
                        .setId(orderGoods.getId()).setGoodsName(orderGoods.getGoodsName()).setNumber(orderGoods.getNumber())
                        .setPicUrl(orderGoods.getPicUrl()).setSpecifications(orderGoods.getSpecifications()).setPrice(orderGoods.getPrice()).setTaxPrice(orderGoods.getTaxPrice())
                        .setFormulaMaterialList(getOrderGoodsFormulaMaterialList(orderGoods.getOrderId(),orderGoods.getId())).setPropertyList(getOrderGoodsPropertyList(orderGoods.getOrderId(),orderGoods.getId())).setTaxList(getOrderGoodsTaxList(orderGoods.getOrderId(),orderGoods.getId())));
                orderPackageResp.setGoodsList(orderPackageGoodsRespList);
                return orderPackageResp;
            });
            orderRespVO.setPackageList(orderPackageRespList);
        }
        return ResponseUtil.ok(orderRespVO);

        /*OrderDetailResponse response = new OrderDetailResponse();
        BeanUtils.copyProperties(order, response);
        response.setMemberPrice(order.getMemberPrice() == null ? new BigDecimal(0.00).setScale(2) : order.getMemberPrice());
        response.setOrderStatusText(OrderStatusUtil.orderStatusText(order));
        OrderHandleOptionVo orderHandleOptionVo = new OrderHandleOptionVo();
        BeanUtils.copyProperties(OrderStatusUtil.build(order), orderHandleOptionVo);
        response.setHandleOption(orderHandleOptionVo);

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
        List<OrderDetailGoodsVo> goodsList = new ArrayList<>();
        for (LitemallOrderGoods orderGoods : orderGoodsList) {
            OrderDetailGoodsVo goodsVo = new OrderDetailGoodsVo();
            BeanUtils.copyProperties(orderGoods, goodsVo);
            //设置商品不含税总价
            goodsVo.setGoodsPrice(orderGoods.getSellingPrice().multiply(new BigDecimal(orderGoods.getNumber())));
            Integer orderGoodsId = orderGoods.getId();

            //规格
            List<OrderDetailSpecVo> specificationList = new ArrayList<>();
            List<LitemallGoodsSpecification> specLs = goodsSpecificationService.queryByIds(orderGoods.getSpecificationIds());
            for (LitemallGoodsSpecification litemallGoodsSpecification : specLs) {
                OrderDetailSpecVo specVo = new OrderDetailSpecVo();
                BeanUtils.copyProperties(litemallGoodsSpecification, specVo);
                goodsVo.setSpecifPrice(litemallGoodsSpecification.getPrice());
                specificationList.add(specVo);
            }
            goodsVo.setSpecificationList(specificationList);

            //查询辅料
            List<LitemallOrderGoodsAccessory> orderGoodsAccessories = litemallOrderGoodsAccessoryService.findByOrderGoodsId(orderGoodsId);
            if (orderGoodsAccessories != null && orderGoodsAccessories.size() > 0) {
                goodsVo.setAccessoryVos(new ArrayList<>());
                for (LitemallOrderGoodsAccessory orderGoodsAccessory : orderGoodsAccessories) {
                    LitemallGoodsAccessory goodsAccessory = litemallGoodsAccessoryService.findById(orderGoodsAccessory.getAccessoryId());
                    if (goodsAccessory != null) {
                        OrderDetailAccessoryVo accessoryVo = new OrderDetailAccessoryVo();
                        BeanUtils.copyProperties(goodsAccessory, accessoryVo);

                        accessoryVo.setUnitPrice(goodsAccessory.getPrice().setScale(2));
                        accessoryVo.setSelectNum(orderGoodsAccessory.getNumber());
                        accessoryVo.setPrice(orderGoodsAccessory.getPrice().setScale(2));
                        LitemallMerchandise merchandise = litemallMerchandiseService.findById(goodsAccessory.getMerchandiseId());
                        if (merchandise != null) {
                            accessoryVo.setUnit(merchandise.getBasicUnit());
                        }
                        goodsVo.getAccessoryVos().add(accessoryVo);
                    }
                }
            }

            //查询属性
            List<LitemallOrderGoodsProperty> propertyList = litemallOrderGoodsPropertyService.queryByOrderGoodsId(orderGoodsId);
            if (!CollectionUtils.isEmpty(propertyList)) {
                List<OrderDetailPropVo> collect = propertyList.stream().map(item -> {
                    LitemallGoodsProperty litemallGoodsProperty = litemallGoodsPropertyService.findById(item.getGoodsPropertyId());
                    OrderDetailPropVo propVo = new OrderDetailPropVo();
                    BeanUtils.copyProperties(litemallGoodsProperty, propVo);
                    propVo.setSelectValue(item.getValue());
                    return propVo;
                }).collect(Collectors.toList());
                goodsVo.setPropList(collect);
            }

            goodsList.add(goodsVo);
        }
        response.setGoodsList(goodsList);

        //税费
        List<LitemallOrderTax> litemallOrderTaxes = litemallOrderTaxService.queryByOrderId(order.getId());
        Map<String, List<LitemallOrderTax>> taxGroupMap = litemallOrderTaxes.stream().collect(Collectors.groupingBy(LitemallOrderTax::getCode));
        List<OrderDetailTaxCodeVo> orderTaxes = new ArrayList<>();
        for (Map.Entry<String, List<LitemallOrderTax>> entry : taxGroupMap.entrySet()) {
            OrderDetailTaxCodeVo taxCodeVo = new OrderDetailTaxCodeVo();
            taxCodeVo.setCode(entry.getKey());

            List<OrderDetailTaxVo> taxs = new ArrayList<>();
            List<LitemallOrderTax> orderTaxLs = entry.getValue();
            for (LitemallOrderTax orderTax : orderTaxLs) {
                OrderDetailTaxVo orderGetNewTaxVo = new OrderDetailTaxVo();
                BeanUtils.copyProperties(orderTax, orderGetNewTaxVo);

                taxs.add(orderGetNewTaxVo);
            }
            taxCodeVo.setTaxs(taxs);
            orderTaxes.add(taxCodeVo);
        }
        response.setOrderTaxes(orderTaxes);

        response.setGSTPrice(order.getGstPrice());
        response.setPSTPrice(order.getPstPrice());
        response.setHSTPrice(order.getHstPrice());
        response.setMemberPer(order.getMemberPer());
        response.setWxMemberSource(JSONUtil.toList(JSONUtil.parseArray(order.getWxMemberSource()),WxMemberSourceDTO.class));
        // 订单状态为已发货且物流信息不为空
        //"YTO", "800669400640887922"
        if ((Constants.ORDER_STATUS_PICKUP.equals(order.getOrderStatus())) && (Constants.ORDER_SEND.equals(order.getOrderType()))) {
            ExpressInfo ei = expressService.getExpressInfo(order.getShipChannel(), order.getShipSn());
            response.setExpressInfo(ei);
        }
        if (response.getPoints() != null) {
            response.setPoints(new BigDecimal(response.getPoints().intValue()));
        }
        if (response.getActualPrice() != null) {
            response.setActualPrice(response.getActualPrice().setScale(2));
        }

        if (response.getCouponPrice() != null) {
            response.setCouponPrice(response.getCouponPrice().setScale(2));
        }

        if (response.getTaxPrice() != null) {
            response.setTaxPrice(response.getTaxPrice().setScale(2));
        }

        if (response.getGoodsPrice() != null) {
            response.setGoodsPrice(response.getGoodsPrice().setScale(2));
        }

        return ResponseUtil.ok(response);*/
    }


    private OrderSubmitCheckRespVO checkShopMaterial(OrderSubmitReqVO reqVO){
        List<String> materialNameList = new ArrayList<>();
        for (CartListRespVO cartListRespVO : reqVO.getCartList()) {
            if(cartListRespVO.getType()==0){
                CartListRespVO.CartGoodsRespVO cartGoods = cartListRespVO.getCartGoods();
                for (CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO goodsFormulaSpecificationsDataProportioning : cartGoods.getSpecificationsDataProportioningList()) {
                    LumiereFormulaSpecificationsDataProportioning proportioningServiceById = lumiereFormulaSpecificationsDataProportioningService.getById(goodsFormulaSpecificationsDataProportioning.getFormulaSpecificationsDataProportioningId());
                    merchandiseSubtract(materialNameList,goodsFormulaSpecificationsDataProportioning.getMaterialId(),cartGoods.getNumber()*goodsFormulaSpecificationsDataProportioning.getQuantity()*proportioningServiceById.getSpecificationsDose(),reqVO.getShop().getId());
                }
            }else {
                CartListRespVO.CartPackageRespVO cartListPackage = cartListRespVO.getCartListPackage();
                for (CartListRespVO.CartGoodsRespVO cartGoods : cartListPackage.getCartListGoodsList()) {
                    for (CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO goodsFormulaSpecificationsDataProportioning : cartGoods.getSpecificationsDataProportioningList()) {
                        LumiereFormulaSpecificationsDataProportioning proportioningServiceById = lumiereFormulaSpecificationsDataProportioningService.getById(goodsFormulaSpecificationsDataProportioning.getFormulaSpecificationsDataProportioningId());
                        merchandiseSubtract(materialNameList,goodsFormulaSpecificationsDataProportioning.getMaterialId(),cartGoods.getNumber()*goodsFormulaSpecificationsDataProportioning.getQuantity()*proportioningServiceById.getSpecificationsDose(),reqVO.getShop().getId());
                    }
                }
            }
        }
        return new OrderSubmitCheckRespVO(materialNameList.size()>0,materialNameList);
    }

    private List<String> merchandiseSubtract(List<String> materialNameList,Integer materialId,Double quantity,Integer shopId){
        //对比每一个的库存
        LitemallMerchandise merchandise = litemallMerchandiseService.findById(materialId);
        LitemallShopMerchandise shopMerchandise = litemallShopMerchandiseService.queryByMerIdAndShopId(merchandise.getId(), shopId);
        if (shopMerchandise==null){
            materialNameList.add(merchandise.getName());
            return materialNameList;
        }
        if(shopMerchandise.getBasicNumber()<quantity){
            //原料不足
            materialNameList.add(merchandise.getName());
        }else {
            //减去库存
            Double basicNumber = shopMerchandise.getBasicNumber()-quantity;
            Double number = basicNumber/merchandise.getCheckRatio();
            shopMerchandise.setNumber(NumberUtil.roundDown(number,2).doubleValue());
            shopMerchandise.setBasicNumber(NumberUtil.roundDown(basicNumber,2).doubleValue());
            shopMerchandise.setStockNumber(NumberUtil.roundDown(number/merchandise.getRatio(),2).doubleValue());
            litemallShopMerchandiseService.updateById(shopMerchandise);
        }
        return materialNameList;
    }

    @Transactional
    public Response submitOrder(Integer userId, OrderSubmitReqVO reqVO) {
        //检测原料库存
        OrderSubmitCheckRespVO submitCheckRespVO = checkShopMaterial(reqVO);
        if(submitCheckRespVO.getCheckResult()){
            return ResponseUtil.fail(ErrorCodeConstants.LUMIERE_GOODS_MERCHANDISE_NOTENOUGH.getCode(), submitCheckRespVO.getMaterialNameList().toString());
        }
        //创建订单
        LitemallOrder order =  createOrder( userId, reqVO);
        //套餐Ids 商品Ids
        List<Integer> orderGoodsIds = new ArrayList<>();
        List<Integer> packageIds = new ArrayList<>();

        //创建商品 创建套餐
        reqVO.getCartList().forEach(cartListRespVO->{
            if (cartListRespVO.getType() == 0) {
                createOrderGoods(orderGoodsIds, cartListRespVO, order);
            } else {
                createOrderPackageGoods(packageIds, cartListRespVO, order);
            }
        });
        LitemallOrder byId = new LitemallOrder();
        byId.setId(order.getId());
        byId.setPackageIds(packageIds);
        byId.setGoodsIds(orderGoodsIds);
        orderService.updateById(byId);
        //更新优惠券信息
        updateCoupon(reqVO.getCouponId(), order);

        // 添加账本记录
        addAccountBookRecord(reqVO.getShop().getId(), order);

        //清空购物车
        /*for (CartListRespVO cartListRespVO : reqVO.getCartList()) {
            if(cartListRespVO.getType()==0){
                List<CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO> formulaSpecificationsMaterials = cartListRespVO.getCartGoods().getSpecificationsDataProportioningList();
                lumiereCartGoodsFormulaSpecificationsDataProportioningService.removeBatchByIds(CollStreamUtil.toList(formulaSpecificationsMaterials,CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO::getId));
                lumiereCartGoodsPropertyService.removeBatchByIds(CollStreamUtil.toList(cartListRespVO.getCartGoods().getGoodsProperties(),LumiereCartGoodsProperty::getId));
            }else {
                List<CartListRespVO.CartGoodsRespVO> cartListGoodsList = cartListRespVO.getCartListPackage().getCartListGoodsList();
                for (CartListRespVO.CartGoodsRespVO cartGoodsRespVO : cartListGoodsList) {
                    List<CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO> formulaSpecificationsMaterials = cartGoodsRespVO.getSpecificationsDataProportioningList();
                    cartGoodsRespVO.getGoodsProperties();
                }
            }
        }*/
        lumiereCartService.removeBatchByIds(CollStreamUtil.toList(reqVO.getCartList(),CartListRespVO::getId));

        return ResponseUtil.ok(order.getId());
    }
    // 添加账本记录
    private void addAccountBookRecord(Integer shopId, LitemallOrder litemallOrder) {
        addAccountBook(shopId, litemallOrder.getActualPrice(), "App order pay", 0, 0);
    }
    private void addAccountBook(Integer shopId, BigDecimal actualPrice, String remark, Integer recordType, Integer sourceType) {
        LitemallAccountBookFormDto form = new LitemallAccountBookFormDto();
        form.setShopId(shopId);
        form.setRecordType(recordType);
        form.setRecordDate(LocalDateTime.now());
        form.setAmount(actualPrice);
        form.setRemark(remark);
        form.setSourceType(sourceType);
        litemallAccountBookService.create(shopId, form);
    }

    // 更新优惠券信息
    private void updateCoupon(Long  couponUserId, LitemallOrder litemallOrder) {
        if(couponUserId == null)return;
        lumiereCouponUserService.update(Wrappers.lambdaUpdate(LumiereCouponUser.class)
                .eq(LumiereCouponUser::getId, couponUserId)
                .set(LumiereCouponUser::getOrderId, litemallOrder.getId())
                .set(LumiereCouponUser::getShopId, litemallOrder.getShopId())
                .set(LumiereCouponUser::getUsedTime, LocalDateTime.now()));
    }

    private LitemallOrder createOrder(Integer userId, OrderSubmitReqVO reqVO){
        Integer maxSerialNo = orderService.getTodayMaxSerialNo(reqVO.getShop().getId());
        LitemallUser posUser = userService.findById(userId);
        LitemallOrder litemallOrder = new LitemallOrder();
        litemallOrder.setShopId(reqVO.getShop().getId());
        litemallOrder.setUserId(userId);
        litemallOrder.setEmployeeId(ObjectUtil.isNotNull(posUser) ? posUser.getUsername() : "");
        litemallOrder.setOrderSn(RandomUtil.randomNumbers(16));
        litemallOrder.setSerialNo(maxSerialNo + 1);
        litemallOrder.setOrderStatus(ORDER_STATUS_UNPAID);
        litemallOrder.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);
        litemallOrder.setOrderType(reqVO.getOrderType().byteValue());
        litemallOrder.setGoodsPrice(reqVO.getTotalGoodsPrice());
        litemallOrder.setFreightPrice(BigDecimal.ZERO);
        //litemallOrder.setCouponPrice(orderGoodsCheckOut.getCouponPrice());
        litemallOrder.setIntegralPrice(BigDecimal.ZERO);
        litemallOrder.setOrderPrice(reqVO.getTotalPrice());
        litemallOrder.setTaxPrice(reqVO.getTaxTotalPrice());
        litemallOrder.setActualPrice(reqVO.getTotalPrice());
        litemallOrder.setCurrency(DefaultCurType.CAD.getType());
        litemallOrder.setOrderSource(Constants.ORDER_SOURCE_APP);
        litemallOrder.setCouponPrice(reqVO.getCouponDiscountPrice());
        litemallOrder.setPayTime(LocalDateTime.now());
        //litemallOrder.setPayType(reqVO.getPayType().byteValue());
        litemallOrder.setGstPrice(reqVO.getTotalGSTPrice());
        litemallOrder.setPstPrice(reqVO.getTotalPSTPrice());
        litemallOrder.setHstPrice(reqVO.getTotalHSTPrice());
        litemallOrder.setMemberPrice(reqVO.getMemberDiscountSumPrices());
        litemallOrder.setMemberPer(reqVO.getMemberPer());
        litemallOrder.setWxMemberSource(JSONUtil.toJsonStr(reqVO.getWxMemberSourceVOList()));
        litemallOrder.setSerinalNumber(orderService.getTodayMaxSerialNo(reqVO.getShop().getId()) + 1);
        litemallOrder.setShipStatus((byte) 1);
        litemallOrder.setMessage(reqVO.getMessage());
        litemallOrder.setDeleted(false);
        if (reqVO.getOrderType().byteValue() == Constants.ORDER_SEND) {
            LitemallAddress checkedAddress = addressService.query(userId, reqVO.getAddressId());
            litemallOrder.setConsignee(checkedAddress.getName());
            litemallOrder.setMobile(checkedAddress.getTel());
            String detailedAddress = checkedAddress.getProvince() + checkedAddress.getCity() + checkedAddress.getCounty() + " " + checkedAddress.getAddressDetail();
            litemallOrder.setAddress(detailedAddress);
        }
        litemallOrder.setAddTime(LocalDateTime.now());
        orderService.save(litemallOrder);
        return litemallOrder;
    }

    private boolean createOrderGoods(List<Integer> orderGoodsIds,CartListRespVO cartListRespVO, LitemallOrder litemallOrder) {

        // 根据商品ID获取商品信息
        LitemallGoods litemallGoods = goodsService.findById(cartListRespVO.getCartGoods().getGoodsId());

        // 创建订单商品对象
        LitemallOrderGoods litemallOrderGoods = new LitemallOrderGoods();
        litemallOrderGoods.setOrderId(litemallOrder.getId());
        litemallOrderGoods.setShopId(litemallOrder.getShopId());
        litemallOrderGoods.setGoodsName(litemallGoods.getName());
        litemallOrderGoods.setGoodsSn(litemallGoods.getGoodsSn());
        litemallOrderGoods.setCategoryId(litemallGoods.getCategoryId());
        litemallOrderGoods.setNumber(cartListRespVO.getCartGoods().getNumber().shortValue());
        litemallOrderGoods.setTaxPrice(cartListRespVO.getCartGoods().getTaxPrice());
        //litemallOrderGoods.setDiscountPrice(goods.getDiscountPrice());
        litemallOrderGoods.setGoodsId(litemallGoods.getId());

        //只有配方版
        LumiereFormulaSpecifications formulaSpecifications = lumiereFormulaSpecificationsService.getById(cartListRespVO.getCartGoods().getSpecificationId());
        String[] specifications = {formulaSpecifications.getSpecificationsName()};
        litemallOrderGoods.setSpecifications(specifications);
        Integer[] specificationIds = {formulaSpecifications.getId()};

        litemallOrderGoods.setUnitPrice(formulaSpecifications.getSpecificationsPrice());
        litemallOrderGoods.setSellingPrice(cartListRespVO.getPrice());

        litemallOrderGoods.setSpecificationIds(specificationIds);
        litemallOrderGoods.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);
        litemallOrderGoods.setPrice(cartListRespVO.getPrice());
        litemallOrderGoods.setPicUrl(litemallGoods.getPicUrl());
        litemallOrderGoods.setAddTime(LocalDateTime.now());
        litemallOrderGoods.setUpdateTime(LocalDateTime.now());
        litemallOrderGoods.setDeleted(false);
        //制作下标
        List<WebOrderGoodsRemarkDTO> remarkList = new ArrayList<>();
        for (int i = 0; i < cartListRespVO.getCartGoods().getNumber(); i++) {
            remarkList.add(WebOrderGoodsRemarkDTO.builder().index(i).content("").indexMakeStatus(0).build());
        }
        litemallOrderGoods.setRemark(remarkList);
        // 将订单商品保存到数据库
        orderGoodsService.add(litemallOrderGoods);
        orderGoodsIds.add(litemallOrderGoods.getId());

        List<LitemallOrderFormulaMaterial> orderFormulaMaterials = new ArrayList<>();
        List<CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO> formulaSpecificationsMaterials = cartListRespVO.getCartGoods().getSpecificationsDataProportioningList();

        for (CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO cartFormulaSpecificationsMaterial : formulaSpecificationsMaterials) {
            //配方原料
            LumiereFormulaSpecificationsDataProportioning formulaSpecificationsDataProportioning = lumiereFormulaSpecificationsDataProportioningService.getById(cartFormulaSpecificationsMaterial.getFormulaSpecificationsDataProportioningId());

            //原料
            //LumiereFormulaMaterial formulaMaterial = lumiereFormulaMaterialService.getById(formulaSpecificationsDataProportioning.getFormulaMaterialId());
            //订单原料
            LitemallOrderFormulaMaterial orderFormulaMaterial = new LitemallOrderFormulaMaterial();
            orderFormulaMaterial.setOrderId(litemallOrder.getId());
            orderFormulaMaterial.setOrderGoodsId(litemallOrderGoods.getId());
            orderFormulaMaterial.setFormulaId(formulaSpecifications.getFormulaId());
            orderFormulaMaterial.setMaterialId(cartFormulaSpecificationsMaterial.getMaterialId());
            orderFormulaMaterial.setMaterialName(cartFormulaSpecificationsMaterial.getMaterialName());
            orderFormulaMaterial.setMakeUnit(cartFormulaSpecificationsMaterial.getMakeUnit());
            orderFormulaMaterial.setSurcharge(formulaSpecificationsDataProportioning.getSurcharge());
            orderFormulaMaterial.setSpecificationsDose(formulaSpecificationsDataProportioning.getSpecificationsDose());
            orderFormulaMaterial.setQuantity(cartFormulaSpecificationsMaterial.getQuantity());
            orderFormulaMaterial.setPrice(cartFormulaSpecificationsMaterial.getPrice());
            orderFormulaMaterial.setUnit(formulaSpecificationsDataProportioning.getUnit());
            orderFormulaMaterial.setConsumeSystem(formulaSpecificationsDataProportioning.getConsumeSystem());
            orderFormulaMaterial.setMaterialType(formulaSpecificationsDataProportioning.getMaterialType());
            orderFormulaMaterial.setIsDefault(formulaSpecificationsDataProportioning.getIsDefault());
            orderFormulaMaterial.setAddTime(LocalDateTime.now());
            orderFormulaMaterial.setUpdateTime(LocalDateTime.now());
            orderFormulaMaterial.setDeleted(false);
            orderFormulaMaterials.add(orderFormulaMaterial);
        }
        if(CollUtil.isNotEmpty(orderFormulaMaterials)){
            litemallOrderFormulaMaterialService.saveBatch(orderFormulaMaterials);
        }

        // 遍历商品的属性列表，并保存到数据库
        for (LumiereCartGoodsProperty cartGoodsProperty : cartListRespVO.getCartGoods().getGoodsProperties()) {
            if (ObjectUtil.isNotNull(cartGoodsProperty)) {
                LitemallOrderGoodsProperty orderGoodsProperty = new LitemallOrderGoodsProperty();
                orderGoodsProperty.setOrderId(litemallOrder.getId());
                orderGoodsProperty.setOrderGoodsId(litemallOrderGoods.getId());
                orderGoodsProperty.setGoodsId(litemallGoods.getId());
                orderGoodsProperty.setGoodsPropertyId(cartGoodsProperty.getGoodsPropertyId());
                orderGoodsProperty.setName(cartGoodsProperty.getName());
                orderGoodsProperty.setValue(cartGoodsProperty.getValue());
                orderGoodsProperty.setAddTime(LocalDateTime.now());
                orderGoodsProperty.setDeleted(false);
                litemallOrderGoodsPropertyService.add(orderGoodsProperty);
            }
        }

        // 遍历商品的税费列表，并保存到数据库
        if(CollUtil.isNotEmpty(cartListRespVO.getCartGoods().getGoodsTaxList())){
            for (CartListRespVO.CartListGoodsTaxRespVO goodsTax : cartListRespVO.getCartGoods().getGoodsTaxList()) {
                LitemallOrderTax orderTax = new LitemallOrderTax();
                orderTax.setOrderId(litemallOrder.getId());
                orderTax.setOrderGoodsId(litemallOrderGoods.getId());
                orderTax.setGoodsId(litemallGoods.getId());
                orderTax.setCode(goodsTax.getCode());
                orderTax.setValue(goodsTax.getValue());
                orderTax.setPrice(goodsTax.getPrice());
                litemallOrderTaxService.add(orderTax);
            }
        }
        return true;
    }

    private boolean createOrderPackageGoods(List<Integer> packageIds,CartListRespVO cartListRespVO, LitemallOrder litemallOrder) {
        //保存订单套餐
        LumierePackage lumierePackage = lumierePackageService.getById(cartListRespVO.getCartListPackage().getPackageId());
        LitemallOrderPackage orderPackage = BeanUtil.toBean(lumierePackage, LitemallOrderPackage.class);
        orderPackage.setId(null);
        orderPackage.setOrderId(litemallOrder.getId());
        orderPackage.setNumber(cartListRespVO.getCartListPackage().getNumber());
        orderPackage.setAmount(cartListRespVO.getCartListPackage().getPrice());
        //保存订单套餐商品
        List<Integer> orderPackageGoodsIds = new ArrayList<>();

        for (CartListRespVO.CartGoodsRespVO cartGoodsRespVO : cartListRespVO.getCartListPackage().getCartListGoodsList()) {

            // 根据商品ID获取商品信息
            LitemallGoods litemallGoods = goodsService.findById(cartGoodsRespVO.getGoodsId());

            // 创建订单商品对象
            LitemallOrderGoods litemallOrderGoods = new LitemallOrderGoods();
            litemallOrderGoods.setOrderId(litemallOrder.getId());
            litemallOrderGoods.setShopId(litemallOrder.getShopId());
            litemallOrderGoods.setGoodsName(litemallGoods.getName());
            litemallOrderGoods.setGoodsSn(litemallGoods.getGoodsSn());
            litemallOrderGoods.setCategoryId(litemallGoods.getCategoryId());
            litemallOrderGoods.setNumber(cartGoodsRespVO.getNumber().shortValue());
            litemallOrderGoods.setTaxPrice(cartGoodsRespVO.getTaxPrice());

            //litemallOrderGoods.setDiscountPrice(goods.getDiscountPrice());
            litemallOrderGoods.setGoodsId(litemallGoods.getId());

            //只有配方版
            LumiereFormulaSpecifications formulaSpecifications = lumiereFormulaSpecificationsService.getById(cartGoodsRespVO.getSpecificationId());
            String[] specifications = {formulaSpecifications.getSpecificationsName()};
            litemallOrderGoods.setSpecifications(specifications);
            Integer[] specificationIds = {formulaSpecifications.getId()};

            litemallOrderGoods.setUnitPrice(formulaSpecifications.getSpecificationsPrice());
            litemallOrderGoods.setSellingPrice(cartGoodsRespVO.getPrice());

            litemallOrderGoods.setSpecificationIds(specificationIds);
            litemallOrderGoods.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);
            litemallOrderGoods.setPrice(cartGoodsRespVO.getPrice());
            litemallOrderGoods.setPicUrl(litemallGoods.getPicUrl());
            litemallOrderGoods.setAddTime(LocalDateTime.now());
            litemallOrderGoods.setUpdateTime(LocalDateTime.now());
            litemallOrderGoods.setDeleted(false);
            //制作下标
            List<WebOrderGoodsRemarkDTO> remarkList = new ArrayList<>();
            for (int i = 0; i < cartGoodsRespVO.getNumber(); i++) {
                remarkList.add(WebOrderGoodsRemarkDTO.builder().index(i).content("").indexMakeStatus(0).build());
            }
            litemallOrderGoods.setRemark(remarkList);
            // 将订单商品保存到数据库
            orderGoodsService.add(litemallOrderGoods);
            orderPackageGoodsIds.add(litemallOrderGoods.getId());

            List<LitemallOrderFormulaMaterial> orderFormulaMaterials = new ArrayList<>();
            List<CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO> formulaSpecificationsMaterials = cartGoodsRespVO.getSpecificationsDataProportioningList();

            for (CartListRespVO.CartListGoodsFormulaSpecificationsDataProportioningRespVO cartFormulaSpecificationsMaterial : formulaSpecificationsMaterials) {
                //配方原料
                LumiereFormulaSpecificationsDataProportioning formulaSpecificationsDataProportioning = lumiereFormulaSpecificationsDataProportioningService.getById(cartFormulaSpecificationsMaterial.getFormulaSpecificationsDataProportioningId());

                //原料
                //LumiereFormulaMaterial formulaMaterial = lumiereFormulaMaterialService.getById(formulaSpecificationsDataProportioning.getFormulaMaterialId());
                //订单原料
                LitemallOrderFormulaMaterial orderFormulaMaterial = new LitemallOrderFormulaMaterial();
                orderFormulaMaterial.setOrderId(litemallOrder.getId());
                orderFormulaMaterial.setOrderGoodsId(litemallOrderGoods.getId());
                orderFormulaMaterial.setFormulaId(formulaSpecifications.getFormulaId());
                orderFormulaMaterial.setMaterialId(cartFormulaSpecificationsMaterial.getMaterialId());
                orderFormulaMaterial.setMaterialName(cartFormulaSpecificationsMaterial.getMaterialName());
                orderFormulaMaterial.setMakeUnit(formulaSpecificationsDataProportioning.getMakeUnit());
                orderFormulaMaterial.setSurcharge(formulaSpecificationsDataProportioning.getSurcharge());
                orderFormulaMaterial.setSpecificationsDose(formulaSpecificationsDataProportioning.getSpecificationsDose());
                orderFormulaMaterial.setQuantity(cartFormulaSpecificationsMaterial.getQuantity());
                orderFormulaMaterial.setPrice(cartFormulaSpecificationsMaterial.getPrice());
                orderFormulaMaterial.setUnit(formulaSpecificationsDataProportioning.getUnit());
                orderFormulaMaterial.setConsumeSystem(formulaSpecificationsDataProportioning.getConsumeSystem());
                orderFormulaMaterial.setMaterialType(formulaSpecificationsDataProportioning.getMaterialType());
                orderFormulaMaterial.setIsDefault(formulaSpecificationsDataProportioning.getIsDefault());
                orderFormulaMaterial.setAddTime(LocalDateTime.now());
                orderFormulaMaterial.setUpdateTime(LocalDateTime.now());
                orderFormulaMaterial.setDeleted(false);
                orderFormulaMaterials.add(orderFormulaMaterial);
            }
            if(CollUtil.isNotEmpty(orderFormulaMaterials)){
                litemallOrderFormulaMaterialService.saveBatch(orderFormulaMaterials);
            }

            // 遍历商品的属性列表，并保存到数据库
            for (LumiereCartGoodsProperty cartGoodsProperty : cartGoodsRespVO.getGoodsProperties()) {
                if (ObjectUtil.isNotNull(cartGoodsProperty)) {
                    LitemallOrderGoodsProperty orderGoodsProperty = new LitemallOrderGoodsProperty();
                    orderGoodsProperty.setOrderId(litemallOrder.getId());
                    orderGoodsProperty.setOrderGoodsId(litemallOrderGoods.getId());
                    orderGoodsProperty.setGoodsId(litemallGoods.getId());
                    orderGoodsProperty.setGoodsPropertyId(cartGoodsProperty.getGoodsPropertyId());
                    orderGoodsProperty.setName(cartGoodsProperty.getName());
                    orderGoodsProperty.setValue(cartGoodsProperty.getValue());
                    orderGoodsProperty.setAddTime(LocalDateTime.now());
                    orderGoodsProperty.setDeleted(false);
                    litemallOrderGoodsPropertyService.add(orderGoodsProperty);
                }
            }

            // 遍历商品的税费列表，并保存到数据库
            if(CollUtil.isNotEmpty(cartGoodsRespVO.getGoodsTaxList())){
                for (CartListRespVO.CartListGoodsTaxRespVO goodsTax : cartGoodsRespVO.getGoodsTaxList()) {
                    LitemallOrderTax orderTax = new LitemallOrderTax();
                    orderTax.setOrderId(litemallOrder.getId());
                    orderTax.setOrderGoodsId(litemallOrderGoods.getId());
                    orderTax.setGoodsId(litemallGoods.getId());
                    orderTax.setCode(goodsTax.getCode());
                    orderTax.setValue(goodsTax.getValue());
                    orderTax.setPrice(goodsTax.getPrice());
                    litemallOrderTaxService.add(orderTax);
                }
            }
        }
        orderPackage.setGoodsIds(orderPackageGoodsIds);

        litemallOrderPackageService.save(orderPackage);
        packageIds.add(orderPackage.getId());
        return true;
    }
    /**
     * 提交订单
     * <p>
     * 1. 创建订单表项和订单商品表项;
     * 1-1.判断商品是否上架
     * 1-2.从商品中获取实际商品价格和商品税费
     * 2. 购物车清空;
     * 3. 优惠券设置已用;
     * 4. 商品货品库存减少;
     * 5. 如果是团购商品，则创建团购活动表项。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ cartId：xxx, addressId: xxx, couponId: xxx, message: xxx, grouponRulesId: xxx,  grouponLinkId: xxx}
     * @return 提交订单操作结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Object submit(Integer userId, String body) throws InterruptedException {
        if (body == null) {
            return ResponseUtil.badArgument();
        }
        /**
         * 订单商品项
         */
        List<OrderGoodsBo> orderGoodsList = new ArrayList<>();
        /**
         * 税费
         */
//        List<LitemallOrderTax> orderTaxes = new ArrayList<>();
        //辅料
//        List<LitemallOrderGoodsAccessory> orderGoodsAccessories = new ArrayList<>();
        List<Integer> cartIds = JacksonUtil.parseIntegerList(body, "cartIds");
        Integer addressId = JacksonUtil.parseInteger(body, "addressId");
        Long couponId = JacksonUtil.parseLong(body, "couponId");
        Integer shopId = JacksonUtil.parseInteger(body, "shopId");
        String message = JacksonUtil.parseString(body, "message");
        Integer integral = JacksonUtil.parseInteger(body, "integral");

        //订单类型（1：自提订单;2:外送订单）
        Integer orderType = JacksonUtil.parseInteger(body, "orderType");

        if ((userId == null && (cartIds == null || cartIds.size() == 0)) || couponId == null || orderType == null || shopId == null) {
            return ResponseUtil.badArgument();
        }

        if (orderType.byteValue() == Constants.ORDER_SEND && addressId == null) {
            return ResponseUtil.badArgument();
        }

        //付费会员优惠
        List<LumierePayMemberUser> payMemberUsers = payMemberUserService.listMemberByUserId(userId);

        Integer cityRegionId = getShopRegionId(shopId);
        BigDecimal memberPer = new BigDecimal(0);
        //优惠来源
        List<WxMemberSourceDTO> wxMemberSourceDTOS = CollUtil.newArrayList();
        Boolean notOverlay = false;
        BigDecimal maxMemberPer = new BigDecimal(0);
        //叠加付费会员优惠比例
        for(LumierePayMemberUser payMemberUser : payMemberUsers){
            //获得付费会员
            LumierePayMember payMember = lumierePayMemberService.findById(payMemberUser.getPayMemberId());
            //判断可以在该店使用
            Boolean result = payMember.getShopIds()!=null?ArrayUtil.contains(payMember.getShopIds(), cityRegionId):true;
            //当付费会员允许 汇率叠加
            if(payMember.getIsOverlay()==1 && result &&payMember.getDicountPer() != null){
                memberPer=memberPer.add((payMember.getDicountPer().divide(new BigDecimal(100)))).setScale(2, BigDecimal.ROUND_HALF_UP);
                //会员优惠来源
                wxMemberSourceDTOS.add(new WxMemberSourceDTO(payMember.getDicountPer().divide(new BigDecimal(100)),payMember.getName()));
                notOverlay=true;
            }
            //选择一个最高的会员优惠率
            if(payMember.getDicountPer()!=null&&(memberPer.compareTo(payMember.getDicountPer())==-1)){
                maxMemberPer=payMember.getDicountPer();
            }
        }
        //如果没有一个会员叠加，则选择一个最高的会员优惠率
        memberPer=notOverlay==false?maxMemberPer.divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP):memberPer;

        // 收货地址
        LitemallAddress checkedAddress = null;
        if (addressId != null) {
            checkedAddress = addressService.query(userId, addressId);
            if (orderType.byteValue() == Constants.ORDER_SEND && checkedAddress == null) {
                return ResponseUtil.badArgument();
            }
        }

        LitemallShop litemallShop = shopService.findById(shopId);
        if (!Arrays.asList(litemallShop.getTypes()).contains(orderType)) {
            return ResponseUtil.fail(SHOP_UNSUPPOT, "不支持该服务");
        }
        if (orderType.byteValue() == Constants.ORDER_SEND) {
            if (litemallShop.getLatitude() == null || litemallShop.getLongitude() == null || checkedAddress.getLatitude() == null || checkedAddress.getLongitude() == null) {
                return ResponseUtil.fail(WxResponseEnum.UNKOWN_LOCATION);
            }
            //外送订单判断距离
            Double distance = LocationUtils.getDistance(litemallShop.getLatitude().doubleValue(), litemallShop.getLongitude().doubleValue(), checkedAddress.getLatitude().doubleValue(), checkedAddress.getLongitude().doubleValue());
            if (distance > litemallShop.getRange() * 1000) {
                return ResponseUtil.fail(SHOP_TOO_LONG, "超过配送距离");
            }
        }
        // 货品价格
        List<LitemallCart> checkedGoodsList = null;
        if (cartIds == null || cartIds.size() == 0) {
            checkedGoodsList = cartService.queryByUidAndChecked(userId);
        } else {
            checkedGoodsList = cartService.findByIds(cartIds);
        }
        if (checkedGoodsList.size() == 0) {
            return ResponseUtil.badArgumentValue();
        }

        //优惠券抵扣价格
        BigDecimal couponPrice = new BigDecimal(0.00);

        /**
         * 商品价格
         */
        BigDecimal checkedGoodsPrice = new BigDecimal(0.00);


        // 商品优惠价格，如会员减免、满减、阶梯价等
        for (LitemallCart checkGoods : checkedGoodsList) {
            //初始化
            OrderGoodsBo orderGoodsBo = new OrderGoodsBo();
            orderGoodsBo.setLitemallOrderGoodsAccessories(new ArrayList<>());
            orderGoodsBo.setLitemallOrderTaxes(new ArrayList<>());
            orderGoodsBo.setLitemallOrderGoodsProperties(new ArrayList<>());

            Integer goodsId = checkGoods.getGoodsId();
            LitemallGoods litemallGoods = goodsService.findById(goodsId);
            if (litemallGoods == null) {
                return ResponseUtil.fail(GOODS_UNKNOWN, "商品不存在");
            } else if (!litemallGoods.getIsOnSale()) {
                return ResponseUtil.fail(GOODS_UNSHELVE, "商品已下架");
            }

            //保存商品属性
            List<LitemallCartGoodsProperty> propertyList = litemallCartGoodsPropertyService.queryByCartId(checkGoods.getId());
            if (!CollectionUtils.isEmpty(propertyList)) {
                for (LitemallCartGoodsProperty litemallCartGoodsProperty : propertyList) {
                    LitemallOrderGoodsProperty litemallOrderGoodsProperty = new LitemallOrderGoodsProperty();
                    BeanUtils.copyProperties(litemallCartGoodsProperty, litemallOrderGoodsProperty);

                    orderGoodsBo.getLitemallOrderGoodsProperties().add(litemallOrderGoodsProperty);
                }
            }

//            Integer productId = checkGoods.getProductId();
//            LitemallGoodsProduct goodsProduct = productService.findById(productId);
            //  规格价格
            BigDecimal specGoodsPrice = new BigDecimal(0.00);
            if (checkGoods.getSpecificationIds() != null) {
                for (Integer sid : checkGoods.getSpecificationIds()) {
                    LitemallGoodsSpecification specificationServiceById = goodsSpecificationService.findById(sid);
                    if (specificationServiceById != null) {
                        specGoodsPrice = specGoodsPrice.add(specificationServiceById.getPrice());
                    }
                }
            }

            //  辅料价格
            List<LitemallCartGoodsAccessory> accessories = litemallCartGoodsAccessoryService.queryByCartId(checkGoods.getId());
            BigDecimal acceGoodsPrice = new BigDecimal(0.00);
            if (accessories != null && accessories.size() > 0) {
                for (LitemallCartGoodsAccessory item : accessories) {
                    LitemallGoodsAccessory accessory = litemallGoodsAccessoryService.findById(item.getAccessoryId());
                    if (accessory != null) {
                        /**
                         * 记录订单辅料项
                         */
                        LitemallOrderGoodsAccessory orderGoodsAccessory = new LitemallOrderGoodsAccessory();
                        orderGoodsAccessory.setGoodsId(goodsId);
                        orderGoodsAccessory.setAccessoryId(accessory.getId());
                        orderGoodsAccessory.setAccessoryName(accessory.getGroupName());
                        orderGoodsAccessory.setNumber(item.getNumber());

                        //辅料计算价格
                        Integer costType = accessory.getCostType();
                        if (Constants.ACCESSORY_COST_TYPE_TIME == costType) {//按次计费只需增加一次费用
                            orderGoodsAccessory.setPrice(accessory.getPrice());
                        } else {//按份计算
                            if (item.getNumber() > 0) {
                                orderGoodsAccessory.setPrice(accessory.getPrice().multiply(new BigDecimal(item.getNumber())));
                            } else {
                                orderGoodsAccessory.setPrice(accessory.getPrice());
                            }
                        }
                        acceGoodsPrice = acceGoodsPrice.add(orderGoodsAccessory.getPrice());
                        //    acceGoodsPrice = acceGoodsPrice.add(accessory.getPrice().multiply(new BigDecimal(item.getNumber())));

                        orderGoodsBo.getLitemallOrderGoodsAccessories().add(orderGoodsAccessory);
                    }
                }
            }
            logger.debug("WxOrderService [submit] specGoodsPrice is: " + specGoodsPrice.toString());
            if (specGoodsPrice.add(acceGoodsPrice).compareTo(checkGoods.getPrice()) != 0) {
                return ResponseUtil.fail(GOODS_PRICE_CHANGE, "商品价格已更新，请重新添加商品");
            }
            checkedGoodsPrice = checkedGoodsPrice.add(checkGoods.getPrice().multiply(new BigDecimal(checkGoods.getNumber())));

            /**
             * 设置订单商品表单项
             */
            LitemallOrderGoods orderGoods = new LitemallOrderGoods();
            orderGoods.setGoodsId(checkGoods.getGoodsId());
            orderGoods.setGoodsSn(checkGoods.getGoodsSn());
            orderGoods.setProductId(checkGoods.getProductId());
            orderGoods.setGoodsName(checkGoods.getGoodsName());
            orderGoods.setCategoryId(litemallGoods.getCategoryId());
            orderGoods.setPicUrl(checkGoods.getPicUrl());
            orderGoods.setNumber(checkGoods.getNumber());
//            orderGoods.setTaxPrice(taxPrice);
            orderGoods.setUnitPrice(specGoodsPrice);
            //售价为商品规格价加上辅料价格
            orderGoods.setSellingPrice(checkGoods.getPrice());
//            orderGoods.setPrice(cartGoodsPrice.add(taxPrice));
            orderGoods.setSpecifications(checkGoods.getSpecifications());
            orderGoods.setSpecificationIds(checkGoods.getSpecificationIds());
            orderGoodsBo.setLitemallOrderGoods(orderGoods);

            orderGoodsList.add(orderGoodsBo);
        }

        BigDecimal nowPrice = checkedGoodsPrice;
        BigDecimal memberPrice = new BigDecimal(0);
        if(memberPer.compareTo(new BigDecimal(1))  != 0 ){
            memberPrice = checkedGoodsPrice.compareTo(checkedGoodsPrice.multiply(memberPer)) >= 0?checkedGoodsPrice.multiply(memberPer) : checkedGoodsPrice ;
            checkedGoodsPrice = nowPrice.subtract(memberPrice);
        }
        nowPrice = null;

        /**
         * 优惠券优惠价格
         */
        // 如果couponId=0则没有优惠券，couponId=-1则不使用优惠券
        if (couponId != 0 && couponId != -1) {
            //List<Integer> cartIds1 = checkedGoodsList.stream().map(LitemallCart::getId).collect(Collectors.toList());
            //LitemallCoupon coupon = couponVerifyService.checkCoupon(userId, couponId, cartIds1);
            LumiereCouponUser lumiereCouponUser = lumiereCouponUserService.getById(couponId);
            if (lumiereCouponUser != null) {
                LumiereCouponStrategy couponStrategy = lumiereCouponStrategyService.getById(lumiereCouponUser.getStrategyId());
                if (couponStrategy.getDiscountType() == Constants.DISCOUNT_TYPE_RATE) {
                    couponPrice = checkedGoodsPrice.multiply(couponStrategy.getDiscountRate()).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                } else {
                    couponPrice = couponStrategy.getDiscount();
                }
                //使用优惠券
                lumiereCouponUser.setUsedTime(LocalDateTime.now());
                lumiereCouponUserService.updateById(lumiereCouponUser);
            }
        }

        // 可以使用的其他钱，例如用户积分
        BigDecimal integralPrice = new BigDecimal(0.00);

        //实际的订单费用
        BigDecimal actualGoodsPrice = checkedGoodsPrice.subtract(couponPrice).subtract(integralPrice);
        actualGoodsPrice = actualGoodsPrice.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : actualGoodsPrice;


        // 订单税费
        BigDecimal taxGoodsPrice = new BigDecimal(0.00);

        BigDecimal totalGSTPrice = new BigDecimal(0.00);
        BigDecimal totalPSTPrice = new BigDecimal(0.00);
        BigDecimal totalHSTPrice = new BigDecimal(0.00);
        for (OrderGoodsBo orderGoodsBo : orderGoodsList) {
            BigDecimal taxPrice = BigDecimal.ZERO;
            //税率代码(GST、PST、HST) 税收值 单次计算
            BigDecimal GSTPrice = new BigDecimal(0.00);
            BigDecimal PSTPrice = new BigDecimal(0.00);
            BigDecimal HSTPrice = new BigDecimal(0.00);
            LitemallOrderGoods orderGoods = orderGoodsBo.getLitemallOrderGoods();
            /**
             * 获取商品选用税费
             */
            LitemallGoodsRegion goodRegion = goodsRegionService.findByGidAndCityId(orderGoods.getGoodsId(), cityRegionId);
            if (null == goodRegion) {
                return ResponseUtil.fail(GOODS_SHOP_INVALID, "商品不属于该店铺区域");
            }
            Integer[] taxTypes = goodRegion.getTaxTypes();

            //订单商品费用
            //BigDecimal goodsPrice = orderGoods.getSellingPrice().multiply(new BigDecimal(orderGoods.getNumber()));
            //优惠后商品单价
//        	BigDecimal afterDiscountPrice = orderGoods.getSellingPrice().multiply(actualGoodsPrice).divide(checkedGoodsPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
            /**
             * 商品支付价格= 商品售价* 订单支付价格/订单商品总价
             * 实际支付价格= 商品价格 - 优惠券价格
             */
            BigDecimal afterDiscountPrice = checkedGoodsPrice.compareTo(BigDecimal.ZERO) > 0 ? orderGoods.getSellingPrice().multiply(new BigDecimal(1).subtract(memberPer)).multiply(actualGoodsPrice).divide(checkedGoodsPrice, 2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
            BigDecimal afterDiscountGoodsPrice = afterDiscountPrice.multiply(new BigDecimal(orderGoods.getNumber()));

            for (int j = 0; j < taxTypes.length; j++) {
                Integer taxType = taxTypes[j];
                LitemallTax litemallTax = litemallTaxService.findById(taxType);
                if (null == litemallTax) {
                    return ResponseUtil.fail(TAX_NOT_EXIST, "商品在该店铺区域设置的税费类型不存在");
                } else if (litemallTax.getDeleted() || (!litemallTax.getEnable())) {
                    continue;
                }

                //创建订单税收对象
                LitemallOrderTax orderTax = new LitemallOrderTax();
                orderTax.setGoodsId(orderGoods.getGoodsId());
                orderTax.setCode(litemallTax.getCode());
                orderTax.setName(litemallTax.getName());
                //获取税收值
                BigDecimal value = litemallTax.getValue();
                orderTax.setValue(value);
                BigDecimal price = afterDiscountGoodsPrice.compareTo(BigDecimal.ZERO) > 0 ? afterDiscountGoodsPrice.multiply(value).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
                orderTax.setPrice(price);
                orderGoodsBo.getLitemallOrderTaxes().add(orderTax);
                switch (litemallTax.getCode()){
                    case "GST":
                        GSTPrice=afterDiscountGoodsPrice.compareTo(BigDecimal.ZERO) > 0 ? GSTPrice.add(afterDiscountGoodsPrice.multiply(value).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP)) : BigDecimal.ZERO;
                        break;
                    case "HST":
                        HSTPrice=afterDiscountGoodsPrice.compareTo(BigDecimal.ZERO) > 0 ? HSTPrice.add(afterDiscountGoodsPrice.multiply(value).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP)) : BigDecimal.ZERO;
                        break;
                    //要么是 PST
                    default:
                        PSTPrice=afterDiscountGoodsPrice.compareTo(BigDecimal.ZERO) > 0 ? PSTPrice.add(afterDiscountGoodsPrice.multiply(value).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP)) : BigDecimal.ZERO;
                }
                //taxPrice = taxPrice.add(price);
            }
            /**
             * 商品优惠完之后的价格
             */
            taxPrice = taxPrice.add(GSTPrice.add(PSTPrice).add(HSTPrice));
            orderGoods.setDiscountPrice(afterDiscountPrice);
            orderGoods.setTaxPrice(taxPrice);
            orderGoods.setPrice(afterDiscountGoodsPrice.add(taxPrice));

            //税费 = 商品价格 * 商品数量 * 税率
            taxGoodsPrice = taxGoodsPrice.add(taxPrice);

            totalGSTPrice = totalGSTPrice.add(GSTPrice);
            totalPSTPrice = totalPSTPrice.add(PSTPrice);
            totalHSTPrice = totalHSTPrice.add(HSTPrice);
        }

        /**
         * 计算其他价格
         */

        // 根据订单商品总价计算运费，满足条件（例如88元）则免运费，否则需要支付运费（例如8元）；
        BigDecimal freightPrice = new BigDecimal(0.00);
        if (orderType.byteValue() == Constants.ORDER_SEND && checkedGoodsPrice.compareTo(SystemConfig.getFreightLimit()) < 0) {
            freightPrice = SystemConfig.getFreight();
        }

        // 订单费用
        BigDecimal orderTotalPrice = checkedGoodsPrice.add(taxGoodsPrice).subtract(couponPrice).max(new BigDecimal(0.00));
        // 最终支付费用
        BigDecimal actualPrice = orderTotalPrice.add(freightPrice).subtract(integralPrice);
        Integer orderId = null;
        // 订单
        LitemallOrder order = new LitemallOrder();
        order.setUserId(userId);
        order.setOrderSn(orderService.generateOrderSn(userId));
        order.setOrderStatus(ORDER_STATUS_UNPAID);
        //查询今天的最大取餐序号
        Integer maxSerialNo = orderService.getTodayMaxSerialNo(shopId);
        order.setSerialNo(maxSerialNo + 1);
        order.setOrderSource(Constants.ORDER_SOURCE_APP);
        if (orderType.byteValue() == Constants.ORDER_AET) {
            order.setConsignee("");
            order.setMobile("");
            order.setAddress("");
        } else if (orderType.byteValue() == Constants.ORDER_SEND) {
            order.setConsignee(checkedAddress.getName());
            order.setMobile(checkedAddress.getTel());
            String detailedAddress = checkedAddress.getProvince() + checkedAddress.getCity() + checkedAddress.getCounty() + " " + checkedAddress.getAddressDetail();
            order.setAddress(detailedAddress);
        }

        order.setGstPrice(totalGSTPrice);
        order.setPstPrice(totalPSTPrice);
        order.setHstPrice(totalHSTPrice);
        //付费会员优惠 == 最后的订单价格 * 优惠比例
        order.setMemberPer(memberPer);
        order.setWxMemberSource(JSONUtil.toJsonStr(wxMemberSourceDTOS));


        order.setMessage(message);
        order.setGoodsPrice(checkedGoodsPrice);
        order.setCouponPrice(couponPrice);
        order.setIntegralPrice(integralPrice);
        order.setOrderPrice(orderTotalPrice);
        order.setActualPrice(actualPrice);
        order.setTaxPrice(taxGoodsPrice);
        order.setShopId(shopId);
        order.setOrderType(orderType.byteValue());
        order.setFreightPrice(freightPrice);
        order.setMemberPrice(memberPrice);
        order.setMadeStatus((byte)0);
        order.setMemberId(userId);
        // 添加订单表项
        orderService.add(order);
        orderId = order.getId();


        // 添加订单商品表项
        for (OrderGoodsBo orderGoodsBo : orderGoodsList) {
            // 订单商品
            orderGoodsBo.getLitemallOrderGoods().setOrderId(order.getId());
            orderGoodsBo.getLitemallOrderGoods().setAddTime(LocalDateTime.now());
            orderGoodsBo.getLitemallOrderGoods().setShopId(shopId);

            if(CollUtil.isEmpty(orderGoodsBo.getLitemallOrderGoods().getRemark())){
                List<WebOrderGoodsRemarkDTO> remarkList=new ArrayList<>();
                for (int i=0;i<orderGoodsBo.getLitemallOrderGoods().getNumber();i++){
                    remarkList.add(WebOrderGoodsRemarkDTO.builder().index(i).content("").indexMakeStatus(0).build());
                }
                orderGoodsBo.getLitemallOrderGoods().setRemark(remarkList);
            }

            orderGoodsService.add(orderGoodsBo.getLitemallOrderGoods());

            // 添加辅料表项
            for (LitemallOrderGoodsAccessory item : orderGoodsBo.getLitemallOrderGoodsAccessories()) {
                item.setOrderGoodsId(orderGoodsBo.getLitemallOrderGoods().getId());
                item.setOrderId(orderId);
                litemallOrderGoodsAccessoryService.add(item);
            }

            // 添加订单税费表项
            for (LitemallOrderTax item : orderGoodsBo.getLitemallOrderTaxes()) {
                item.setOrderGoodsId(orderGoodsBo.getLitemallOrderGoods().getId());
                item.setOrderId(orderId);
                litemallOrderTaxService.add(item);
            }

            // 添加订单商品属性
            for (LitemallOrderGoodsProperty item : orderGoodsBo.getLitemallOrderGoodsProperties()) {
                item.setOrderGoodsId(orderGoodsBo.getLitemallOrderGoods().getId());
                item.setOrderId(orderId);
                litemallOrderGoodsPropertyService.add(item);
            }
        }


        // 删除购物车里面的商品信息
        if (cartIds == null || cartIds.size() == 0) {
            cartService.clearGoods(userId);
        } else {
            cartService.clearGoods(userId, cartIds);

        }

        /**
         // 商品货品数量减少
         for (LitemallCart checkGoods : checkedGoodsList) {
         Integer productId = checkGoods.getProductId();
         LitemallGoodsProduct product = productService.findById(productId);

         Integer remainNumber = product.getNumber() - checkGoods.getNumber();
         if (remainNumber < 0) {
         throw new RuntimeException("下单的商品货品数量大于库存量");
         }
         if (productService.reduceStock(productId, checkGoods.getNumber()) == 0) {
         throw new RuntimeException("商品货品库存减少失败");
         }
         }
         // 门店辅料货品数量减少
         for (OrderGoodsBo orderGoodsBo : orderGoodsList) {
         for (LitemallOrderGoodsAccessory item : orderGoodsBo.getLitemallOrderGoodsAccessories()) {
         LitemallGoodsAccessory accessory = litemallGoodsAccessoryService.findById(item.getAccessoryId());
         LitemallShopMerchandise shopMerchandise = litemallShopMerchandiseService.queryByMerIdAndShopId(accessory.getMerchandiseId(), shopId);
         LitemallShopMerchandise update = new LitemallShopMerchandise();
         update.setId(shopMerchandise.getId());
         //实际减少的数量 = 订单商品数 * 每个商品选择的辅料数量
         Integer remainNumber = shopMerchandise.getNumber() - item.getNumber() * orderGoodsBo.getLitemallOrderGoods().getNumber();
         if (remainNumber < 0) {
         throw new RuntimeException("下单的辅料数量大于库存量");
         }
         update.setNumber(shopMerchandise.getNumber() - item.getNumber() * orderGoodsBo.getLitemallOrderGoods().getNumber());
         litemallShopMerchandiseService.updateById(update);
         }
         }
         */

        Map<String, Object> data = new HashMap<>();
        data.put("orderId", orderId);
//        queue.add(order);
//        executorService.submit(()->{
//            try {
//                LitemallOrder o = queue.take();
//                if(o.getOrderStatus() == ORDER_STATUS_UNPAID){
//                    noticeHelper.noticeUser( Constants.MSG_TYPE_ORDER,"order", o.getOrderSn() + "Order Successful",o.getUserId(), o);
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        });

        order.setTime(300);
        //noticeAsync(order);
        return ResponseUtil.ok(data);
    }

    @Async
    public void noticeAsync(LitemallOrder order) {

        delayQueue.put(order);
        executorService.submit(() -> {
            try {
                while (delayQueue.size() != 0) {
                    /**
                     * 取队列头部元素是否过期
                     */
                    LitemallOrder task = delayQueue.poll();

                    LitemallOrder nOrder = null;
                    if (task != null) {
                        nOrder = orderService.findById(order.getId());
                    }
                    if (task != null && ORDER_STATUS_UNPAID.equals(nOrder.getOrderStatus()) == true) {
                        noticeHelper.noticeUser(Constants.MSG_TYPE_ORDER, "order", task.getOrderSn() + "Order unpaid", task.getUserId(), task);
                        delayQueue.take();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 获取店铺的地区id
     *
     * @param shopId
     */
    private Integer getShopRegionId(Integer shopId) {
        List<LitemallShopRegion> litemallShopRegions = litemallShopRegionService.queryByShopId(shopId);
        if (!CollectionUtils.isEmpty(litemallShopRegions)) {
            for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
                LitemallRegion litemallRegion = regionService.findById(litemallShopRegion.getRegionId());
                if (Constants.REGION_TYPE_CITY == litemallRegion.getType()) {
                    return litemallShopRegion.getRegionId();
                }
            }
        }
        return null;
    }

    /**
     * 取消订单
     * <p>
     * 1. 检测当前订单是否能够取消；
     * 2. 设置订单取消状态；
     * 3. 商品货品库存恢复；
     * 4. 返还优惠券；
     * 5. 退回积分；
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 取消订单操作结果
     */
    @Transactional
    public Object cancel(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgumentValue();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        LocalDateTime preUpdateTime = order.getUpdateTime();

        // 检测是否能够取消
        // OrderHandleOption handleOption = OrderUtil.build(order);
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isCancel()) {
            return ResponseUtil.fail(ORDER_CANCEL_FAIL, "订单不能取消");
        }

        // 设置订单已取消状态
        order.setOrderStatus(Constants.ORDER_STATUS_CANCEL);
        order.setEndTime(LocalDateTime.now());
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            throw new RuntimeException("更新数据已失效");
        }

        /**
         // 商品货品数量增加
         List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
         for (LitemallOrderGoods orderGoods : orderGoodsList) {
         Integer productId = orderGoods.getProductId();
         Short number = orderGoods.getNumber();
         if (productService.addStock(productId, number) == 0) {
         throw new RuntimeException("商品货品库存增加失败");
         }
         }
         */

        // 返还优惠券
        List<LitemallCouponUser> couponUsers = couponUserService.queryByOrderId(orderId);
        if (couponUsers != null && couponUsers.size() > 0) {
            for (LitemallCouponUser couponUser : couponUsers) {
                couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
                couponUser.setUsedTime(null);
                couponUser.setOrderId(null);
                couponUserService.recover(couponUser);
            }
        }

        // 如果使用了积分，更新积分
        if (order.getIntegralPrice() != null && order.getIntegralPrice().compareTo(new BigDecimal(0.00)) > 0) {
            String config = SystemConfig.getConfig(SystemConfig.LITEMALL_INTEGRAL_AMOUNT);
            if (!StringUtils.isEmpty(config)) {
                try {
                    double v = Double.parseDouble(config);
                    LitemallUser user = userService.findById(userId);
                    LitemallUser update = new LitemallUser();
                    update.setId(userId);
                    update.setPoints(user.getPoints().add(order.getIntegralPrice().divide(new BigDecimal(v))));
                    userService.updateById(update);
                } catch (Exception e) {
                    logger.info("取消订单，返还积分失败");
                    logger.info(e);
                }
            }

        }

        return ResponseUtil.ok();
    }

    /**
     * 付款订单的预支付会话标识
     * <p>
     * 1. 检测当前订单是否能够付款
     * 2. 微信商户平台返回支付订单ID
     * 3. 设置订单付款状态
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 支付订单ID
     */
    @Transactional
    public Object prepay(Integer userId, String body, HttpServletRequest request) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgumentValue();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        // 检测是否能够取消
//        OrderHandleOption handleOption = OrderUtil.build(order);
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isPay()) {
            return ResponseUtil.fail(ORDER_PAY_FAIL, "订单不能支付");
        }

        LitemallUser user = userService.findById(userId);
        String openid = user.getWeixinOpenid();
        if (openid == null) {
            return ResponseUtil.fail(AUTH_OPENID_UNACCESS, "订单不能支付");
        }
        WxPayMpOrderResult result = null;
        try {
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setOutTradeNo(order.getOrderSn());
            orderRequest.setOpenid(openid);
            orderRequest.setBody("订单：" + order.getOrderSn());
            // 元转成分
            int fee = 0;
            BigDecimal actualPrice = order.getActualPrice();
            fee = actualPrice.multiply(new BigDecimal(100)).intValue();
            orderRequest.setTotalFee(fee);
            orderRequest.setSpbillCreateIp(IpUtil.getIpAddr(request));

            result = wxPayService.createOrder(orderRequest);

            //缓存prepayID用于后续模版通知
            String prepayId = result.getPackageValue();
            prepayId = prepayId.replace("prepay_id=", "");
            LitemallUserFormid userFormid = new LitemallUserFormid();
            userFormid.setOpenid(user.getWeixinOpenid());
            userFormid.setFormid(prepayId);
            userFormid.setIsprepay(true);
            userFormid.setUseamount(3);
            userFormid.setExpireTime(LocalDateTime.now().plusDays(7));
            formIdService.addUserFormid(userFormid);

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.fail(ORDER_PAY_FAIL, "订单不能支付");
        }

        if (orderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }
        return ResponseUtil.ok(result);
    }

    /**
     * 微信付款成功或失败回调接口
     * <p>
     * 1. 检测当前订单是否是付款状态;
     * 2. 设置订单付款成功状态相关信息;
     * 3. 响应微信商户平台.
     *
     * @param request  请求内容
     * @param response 响应内容
     * @return 操作结果
     */
    @Transactional
    public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
        String xmlResult = null;
        try {
            xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
        } catch (IOException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail(e.getMessage());
        }

        WxPayOrderNotifyResult result = null;
        try {
            result = wxPayService.parseOrderNotifyResult(xmlResult);

            if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())) {
                logger.error(xmlResult);
                throw new WxPayException("微信通知支付失败！");
            }
            if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())) {
                logger.error(xmlResult);
                throw new WxPayException("微信通知支付失败！");
            }
        } catch (WxPayException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail(e.getMessage());
        }

        logger.info("处理腾讯支付平台的订单支付");
        logger.info(result);

        String orderSn = result.getOutTradeNo();
        String payId = result.getTransactionId();

        // 分转化成元
        String totalFee = BaseWxPayResult.fenToYuan(result.getTotalFee());
        LitemallOrder order = orderService.findBySn(orderSn);
        if (order == null) {
            return WxPayNotifyResponse.fail("订单不存在 sn=" + orderSn);
        }

        // 检查这个订单是否已经处理过
//        if (OrderUtil.isPayStatus(order) && order.getPayId() != null) {
        if (OrderStatusUtil.isPayStatus(order) && order.getPayId() != null) {
            return WxPayNotifyResponse.success("订单已经处理成功!");
        }

        // 检查支付订单金额
        if (!totalFee.equals(order.getActualPrice().toString())) {
            return WxPayNotifyResponse.fail(order.getOrderSn() + " : Payment amount does not meet totalFee=" + totalFee);
        }

        order.setPayId(payId);
        order.setPayTime(LocalDateTime.now());
        // order.setOrderStatus(OrderUtil.STATUS_PAY);
        order.setOrderStatus(ORDER_STATUS_ONGOING);
        order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
        orderService.updateById(order);

        /*if (orderService.updateWithOptimisticLocker(order) == 0) {
            // 这里可能存在这样一个问题，用户支付和系统自动取消订单发生在同时
            // 如果数据库首先因为系统自动取消订单而更新了订单状态；
            // 此时用户支付完成回调这里也要更新数据库，而由于乐观锁机制这里的更新会失败
            // 因此，这里会重新读取数据库检查状态是否是订单自动取消，如果是则更新成支付状态。
            order = orderService.findBySn(orderSn);
            int updated = 0;
//            if (OrderUtil.isAutoCancelStatus(order)) {
            if (OrderStatusUtil.isCancelStatus(order)) {
                order.setPayId(payId);
                order.setPayTime(LocalDateTime.now());
//                order.setOrderStatus(OrderUtil.STATUS_PAY);
                order.setOrderStatus(ORDER_STATUS_ONGOING);
                order.setMadeStatus(Constants.ORDER_MADE_STATUS_NEW);//更新订单状态为待制作
                updated = orderService.updateWithOptimisticLocker(order);
            }

            // 如果updated是0，那么数据库更新失败
            if (updated == 0) {
                return WxPayNotifyResponse.fail("更新数据已失效");
            }
        }*/


        // 推送厨房端
        posPushSender.pushAll(order.getShopId(), Constants.ORDER_PUSH_TYPE_PAID, null);

        //TODO 发送邮件和短信通知，这里采用异步发送
        // 订单支付成功以后，会发送短信给用户，以及发送邮件给管理员
        notifyService.notifyMail("新订单通知", order.toString());
        // 这里微信的短信平台对参数长度有限制，所以将订单号只截取后6位
        notifyService.notifySmsTemplateSync(order.getMobile(), NotifyType.PAY_SUCCEED, new String[]{orderSn.substring(8, 14)});

        // 请依据自己的模版消息配置更改参数
        String[] parms = new String[]{
                order.getOrderSn(),
                order.getOrderPrice().toString(),
                DateTimeUtil.getDateTimeDisplayString(order.getAddTime()),
                order.getConsignee(),
                order.getMobile(),
                order.getAddress()
        };

        notifyService.notifyWxTemplate(result.getOpenid(), NotifyType.PAY_SUCCEED, parms, "pages/index/index?orderId=" + order.getId());

        return WxPayNotifyResponse.success("处理成功!");
    }

    /**
     * 订单申请退款
     * <p>
     * 1. 检测当前订单是否能够退款；
     * 2. 设置订单申请退款状态。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单退款操作结果
     */
    public Object refund(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findByUserAndId(userId, orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }
        //如果订单正在制作中，则订单不能退款
        if(order.getMadeStatus()==1){
            return ResponseUtil.fail(ORDER_IS_BEING_MADE, "订单正在制作中,不能退款");
        }
        //如果订单中的商品有一个是不能退款的，则订单不能退款
        List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(orderId);

        for (int i = 0; i < orderGoods.size(); i++) {
            LitemallGoods goods = goodsService.findById(orderGoods.get(i).getGoodsId());
            if (!goods.getIsReturn()) {
                return ResponseUtil.fail(ORDER_INVALID_REFUND, "订单不能退款");
            }
        }

//        OrderHandleOption handleOption = OrderUtil.build(order);
        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isRefund()) {
            return ResponseUtil.fail(ORDER_INVALID_REFUND, "订单不能退款");
        }

        if(order.getMadeStatus().equals(1)||order.getMadeStatus().equals(2)){
            return ResponseUtil.fail(ORDER_INVALID_REFUND_MAKE, "订单不能退款，该订单已经在制作中");
        }

        // 设置订单申请退款状态
        order.setOrderStatus(OrderUtil.STATUS_REFUND);
        order.setMadeStatus((byte) -1);
        order.setIsRefund(true);
        order.setRefundStatus(Constants.ORDER_REFUND_STATUS_ONGOING);//设置退款状态为退款中
        order.setOrderStatus(OrderStatusUtil.STATUS_REFUND);
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }

        // 推送pos
        posPushSender.pushAll(order.getShopId(), Constants.ORDER_PUSH_TYPE_REFUND, null);

        //TODO 发送邮件和短信通知，这里采用异步发送
        // 有用户申请退款，邮件通知运营人员
        awsNotifyService.noticeMail(LitemallWXConstants.WX_INVITATION_USER_TITLE_NOTICEMAIL, "There is a refund order notice!", "There is a refund order notice!", getSendTo(order.getShopId()));
        return ResponseUtil.ok();
    }
    private String generateRefundSn() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String now = df.format(LocalDateTime.now());
        return "T" + now + RandomStringUtils.randomAlphanumeric(4);
    }

    /**
     * 确认收货
     * <p>
     * 1. 检测当前订单是否能够确认收货；
     * 2. 设置订单确认收货状态。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object confirm(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isConfirm()) {
            return ResponseUtil.fail(ORDER_CONFIRM_DELIVERY, "订单不能确认收货");
        }

        Short comments = orderGoodsService.getComments(orderId);
        order.setComments(comments);

        order.setOrderStatus(Constants.ORDER_STATUS_FINISHED);
        order.setCompleteTime(LocalDateTime.now());
        LocalDateTime endTime = LocalDateTime.now();
        order.setEndTime(endTime);
        order.setEndYear(endTime.getYear());
        order.setEndMonth(endTime.getMonth().getValue());
        order.setConfirmTime(endTime);
        if (orderService.updateWithOptimisticLocker(order) == 0) {
            return ResponseUtil.updatedDateExpired();
        }
        return ResponseUtil.ok();
    }

    /**
     * 删除订单
     * <p>
     * 1. 检测当前订单是否可以删除；
     * 2. 删除订单。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object delete(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }

        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgument();
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.badArgumentValue();
        }

        OrderHandleOption handleOption = OrderStatusUtil.build(order);
        if (!handleOption.isDelete()) {
            return ResponseUtil.fail(ORDER_CONNOT_DELETE, "订单不能删除");
        }

        // 订单order_status没有字段用于标识删除
        // 而是存在专门的delete字段表示是否删除
        orderService.logicDeleteById(orderId);
        //删除订单商品
        orderGoodsService.logicDeleteByOrderId(orderId);
        //删除订单商品属性
        litemallOrderGoodsPropertyService.logicDeleteByOrderId(orderId);
        //删除订单商品辅料
        litemallOrderGoodsAccessoryService.logicDeleteByOrderId(orderId);
        //删除订单商品税费
        litemallOrderTaxService.logicDeleteByOrderId(orderId);

        return ResponseUtil.ok();
    }

    /**
     * 待评价订单商品信息
     *
     * @param userId  用户ID
     * @param orderId 订单ID
     * @param goodsId 商品ID
     * @return 待评价订单商品信息
     */
    public Object goods(Integer userId, Integer orderId, Integer goodsId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        List<LitemallOrderGoods> orderGoodsList = orderGoodsService.findByOidAndGid(orderId, goodsId);
        int size = orderGoodsList.size();

        Assert.state(size < 2, "存在多个符合条件的订单商品");

        if (size == 0) {
            return ResponseUtil.badArgumentValue();
        }

        LitemallOrderGoods orderGoods = orderGoodsList.get(0);
        return ResponseUtil.ok(orderGoods);
    }

    /**
     * 待评价订单商品信息
     *
     * @param userId       用户ID
     * @param orderGoodsId 订单商品ID
     * @return 待评价订单商品信息
     */
    public Object goods(Integer userId, Integer orderGoodsId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);

        if (null == orderGoods) {
            return ResponseUtil.badArgumentValue();
        }

        return ResponseUtil.ok(orderGoods);
    }

    /**
     * 评价订单商品
     * <p>
     * 确认商品收货或者系统自动确认商品收货后7天内可以评价，过期不能评价。
     *
     * @param userId 用户ID
     * @param body   订单信息，{ orderId：xxx }
     * @return 订单操作结果
     */
    public Object comment(Integer userId, String body) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        Integer orderGoodsId = JacksonUtil.parseInteger(body, "orderGoodsId");
        if (orderGoodsId == null) {
            return ResponseUtil.badArgument();
        }
        LitemallOrderGoods orderGoods = orderGoodsService.findById(orderGoodsId);
        if (orderGoods == null) {
            return ResponseUtil.badArgumentValue();
        }
        Integer orderId = orderGoods.getOrderId();
        LitemallOrder order = orderService.findById(orderId);
        if (order == null) {
            return ResponseUtil.badArgumentValue();
        }
//        if (!OrderStatusUtil.isConfirmStatus(order) && !OrderUtil.isAutoConfirmStatus(order)) {
        if (!OrderStatusUtil.isConfirmStatus(order)) {
            return ResponseUtil.fail(ORDER_COMMENTED, "当前商品不能评价");
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.fail(ORDER_INVALID, "当前商品不属于用户");
        }
        Integer commentId = orderGoods.getComment();
        if (commentId == -1) {
            return ResponseUtil.fail(ORDER_COMMENT_EXPIRED, "当前商品评价时间已经过期");
        }
        if (commentId != 0) {
            return ResponseUtil.fail(ORDER_COMMENTED, "订单商品已评价");
        }

        String content = JacksonUtil.parseString(body, "content");
        Integer star = JacksonUtil.parseInteger(body, "star");
        if (star == null || star < 0 || star > 5) {
            return ResponseUtil.badArgumentValue();
        }
        Boolean hasPicture = JacksonUtil.parseBoolean(body, "hasPicture");
        List<String> picUrls = JacksonUtil.parseStringList(body, "picUrls");
        if (hasPicture == null || !hasPicture) {
            picUrls = new ArrayList<>(0);
        }

        // 1. 创建评价
        LitemallComment comment = new LitemallComment();
        comment.setUserId(userId);
        comment.setType((byte) 0);
        comment.setValueId(orderGoods.getGoodsId());
        comment.setStar(star.shortValue());
        comment.setContent(content);
        comment.setHasPicture(hasPicture);
        comment.setPicUrls(picUrls.toArray(new String[]{}));
        commentService.save(comment);

        // 2. 更新订单商品的评价列表
        orderGoods.setComment(comment.getId());
        orderGoodsService.updateById(orderGoods);

        // 3. 更新订单中未评价的订单商品可评价数量
        Short commentCount = order.getComments();
        if (commentCount > 0) {
            commentCount--;
        }
        order.setComments(commentCount);
        orderService.updateWithOptimisticLocker(order);

        return ResponseUtil.ok();
    }

    /**
     * TODO 这里现在获取的是门店店长的email，后续如有其他负责人则修改
     *
     * @param shopId
     * @return
     */
    private String getSendTo(Integer shopId) {
        List<LitemallAdmin> admins = litemallAdminService.findByShopId(shopId);
        List<LitemallAdmin> litemallAdmins = admins.stream().filter(admin -> {
            return Arrays.asList(admin.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID);
        }).collect(Collectors.toList());
        return CollUtil.isNotEmpty(litemallAdmins)?litemallAdmins.get(0).getEmail():"";
    }



}
